2023.12 ~ 2024.03
2024년 상반기에 진행한 [채용솔루션 - 평가자 서비스 리뉴얼 프로젝트]의 뒤늦은 후기를 남긴다.
배경 및 목표
- 기존 시스템의 한계
- 개발 생산성 저하: JSP와 jQuery 조합은 초기 학습곡선이 낮아 빠른 프로토타이핑이 가능하지만, 서비스된지 10년이 더 지난 지금 유지보수가 어려웠다.
- UI/UX의 부족: jQuery로 DOM을 직접 조작하는 구조라 복잡한 화면이나 상태관리 측면에서 효율성이 떨어졌다.
- 코드 복잡도 증가: 수십명이 거쳐간 프로젝트는 코드의 복잡도가 높고, 재사용과 모듈화가 어려웠다.
- 서비스 노후화: 일부 기능은 동작하지 않거나 이상하게 동작하고 있던 기능들이 있었다.
- 리뉴얼 목표
- 모노레포 구조 구축 : 앞으로 부분적으로 계속 할 리뉴얼 프로젝트를 대비하기 위해 모노레포 구조를 구축한다.
- 개발 효율성 및 협업 환경 개선: React 기반으로 유연성과 확장성이 높은 Design System을 구축하고, 타입스크립트나 기타 라이브러리를 통해 코드 품질을 향상시켜 협업 환경을 개선한다.
- 성능 및 기능 고도화: 자주 사용하는 검색, 필터, 테이블같은 기능을 강화하여 대규모 사용자를 고려한 고성능을 확보한다.
- 사용자 경험(UX) 강화: 평가자들이 실제 사용하는 주요 기능을 재정비하여 개발 효율과 사용자 만족도를 동시 개선한다.
기술 스택 선정 이유
- React + Typescript
- 컴포넌트 기반 아키텍처: 재사용성과 유지보수가 뛰어남.
- 풍부한 커뮤니티/생태계: 다양한 오픈소스 라이브러리와 자료 덕분에 빠른 문제 해결이 가능.
- 평가하는 사이트다보니 부분적인 렌더링 업데이트가 많이 필요한데 Virtual DOM으로 인한 렌더링 효율성 향상.
- 협업 효율성 향상을 통한 생산성 및 안정성 향상.
- 기타 도입 기술
- ATS Design System: 프로젝트 직전에 2명이서 개발한 디자인 시스템으로, 채용 솔루션 표준 UI컴포넌트 사용.
- Recoil: 전역 상태관리를 위해 사용. Recoil의 AtomFamily를 활용해 페이지별 필터나 상태를 유연하게 관리한다.
- TanstackQuery: 서버 상태관리를 위한 라이브러리로 사용. useSuspenseQuery를 통해 선언적인 load관리로 UX, DX 모두 개선.
- Emotion: 평가 시스템 특성상 잦은 상태변화에 대응하기 위해 CSS-in-JS 사용.
- Vite: ESBuild를 내재하고 있는 Vite로 빌드 속도 향상.
주요 개선 내용
레거시 코드들을 분석해서 숨겨져있던 기능들까지, 기존에 제공하고 있던 기능 100%를 구현했다.
기존 기능들을 제외하고 개발한 신규 기능을 나열해봤다.
중반까지 기획자의 부재로 많은 내용들을 직접 기획하며 기능을 개선했다.
- 디자인 시스템(ATS Design System) 도입
- 직전에 구축해둔 ATS Design System을 활용하여 모든 UI를 일관성 있게 재구성
- 버튼, 테이블, 모달, 필터 등 공통 컴포넌트를 재사용 → 개발 생산성 및 유지보수 편의성 대폭 향상
- 검색 기능 개선 (초성 검색)
- 초성만 입력해도 검색 가능하도록 로직 개선
- 예: ‘서류’ 검색 시 ‘ㅅ’만 입력해도 관련된 전형 리스트가 즉시 검색되도록 구현
- 채용 전형이 수백 개 쌓여도 빠르게 원하는 전형을 찾을 수 있음
- 테이블 헤더 개선 (오름차순/내림차순, 열 고정)
- 기존에는 모든 옵션이 헤더 우측 “옵션 버튼” 안에 숨어있어 학습이 필요했음
- 이제는 정렬 아이콘, 열 고정 아이콘 등을 직관적으로 노출하여 사용자 피로도를 낮춤
- 테이블 열 고정 기능은 아이콘에 마우스오버(hover) 시 노출되고, 고정된 열의 아이콘은 항상 노출 → 복잡도는 낮추고, 사용성은 높임
- 작은 해상도 사용자 대비
- 모니터 해상도가 작을 경우 상단 필터 및 각종 기능들이 자동으로 2줄로 보여주도록 처리
- 필터와 추가 필터 영역도 화면 우측과 맞닿는 경우, 필터 영역이 화면 밖으로 넘어가지 않고 우측에 붙어서 움직일 수 있도록 개선
- 사용자들이 작은 해상도에서도 모든 기능을 놓치지 않도록 개선
- 이력서 열람 여부 표시
- 후보자별 이력서 열람/미열람 상태를 테이블에서 바로 체크할 수 있게 구현
- 평가자들이 어느 이력서를 확인했는지 쉽게 파악하여 평가 프로세스를 효율화
- 페이지 전환 후에도 선택한 지원자 유지
- 레거시 환경에선 서버사이드 렌더링으로 인해 페이지 이동 시 선택 상태가 초기화되었다.
- 이번 리뉴얼로 SPA 구조를 적용하고 상태를 클라이언트에서 관리해, **“모든 페이지 전체 선택”**과 “현재 페이지 전체 선택” 기능을 모두 지원할 수 있게 됐다.
- 페이지를 옮겨 다녀도 선택했던 지원자가 사라지지 않아 작업 효율성이 크게 상승했다.
- 지원자 일괄처리 기능
- 일괄 평가, 관심/블랙 등록 및 해제, 평가표 출력 등을 선택한 지원자에게 한번에 적용이 가능해졌다.
- 다수의 지원자를 동시에 관리해야 하는 HR 담당자의 업무 시간을 단축할 수 있었다.
- 이력서 팝업(Resume) & 실시간 연동
- 이름이나 번호를 클릭하면 이력서 팝업 창으로 연결한다.
- 팝업 창에서 평가 결과를 변경하면 window.postMessage 방식으로 메인 테이블에 실시간 반영한다. 이전에 타 서비스와 연동한 기억이 도움이 됐다.
- 레거시 프로젝트와 메시지 통신을 통해 상호작용이 가능 -> 기존 JSP 환경과 React SPA 간 데이터 동기화에 성공했다.
-
필터 & 추가 필터 공통 모듈화
Recoil의 AtomFamily를 활용해, 다양한 페이지에서 필터, 추가 필터를 재사용 가능하도록 공통 컴포넌트화했다. 같은 UI를 각각 독립된 상태로 관리하면서도, 필요 시 공유할 수 있는 구조를 설계했다. -
React 18 Concurrent + Tanstack Query v5로 로딩 최적화
- useSuspenseQuery를 통해 로딩 단계마다 분기 처리를 직접 해주지 않아도, 데이터가 준비된 순간 UI가 자연스럽게 갱신
- 필요한 부분에만 Spinner가 동작하도록 해 UX를 해치지 않으면서도 데이터 로딩 상태를 명확하게 전달
- 개발자의 DX(Developer Experience)도 한층 올라갔다.
어려웠던 점과 해결 방법
-
테이블을 만들 때 엑셀처럼 열 고정 기능을 제공해주기로 했는데 이 기능을 제공하면서 생긴 파생 이슈로 React의 렌더링 정책과 부딪혀서 캐싱을 컨트롤하기 까다로웠다. 적절한 곳에 할당하는 고유한 키로 캐싱문제를 해결하고, React18에서 제공하는 startTransition을 이용해서 렌더링 최적화 이슈를 해결했다.
-
새로운 테이블 기능의 직관성 확보
오름차순/내림차순, 열 고정 등 다양한 기능이 추가되면서 UI가 복잡해지는 것이 우려됐다. 아이콘 노출 방식, hover 시 제어 등 UX 가이드를 마련해 기획을 설득시키고 단순화를 유지하여 호평을 받았다. 심리학에 기반한 UI/UX를 공부해 둔 것이 도움이 되었다. -
React18 Concurrent구조 공유
일반적으로 tanstack-query를 사용할 때 isLoading을 활용한 데이터 패칭 전략을 사용한다.
하지만 Concurrent구조는 이미 데이터가 패칭되었음을 기반으로 코드를 짜기 때문에 이에 대한 설명으로 문서 자료도 만들고 설득의 과정을 거쳐야 했다. 결과적으로 모두 효용성에 대해 공감해주어서 성공적인 구조 설계가 가능했다.
프로젝트를 마치며
“리뉴얼”하면 기존에 잘 돌아가고 있던 서비스를 처음부터 근간을 다시 세우는 일이기 때문에 재밌을 것 같으면서도 걱정이 앞섰다. 하지만, 변화를 두려워하는 것은 인간의 특성임을 받아들이고 한번 부딪혀보기로 했었는데 시간이 지나고보니 기술적인 성장도 성장이지만 두려움이라는 큰 벽을 깬 것 같아서 의미가 컸다.
- 리뉴얼 성과
- 기존 묵혀있던 VOC 100건 이상 해결
- 2023 마이다스 최우수팀(1등) 수상에 크게 기여
- 개발 생산성 증가: 컴포넌트화로 코드 중복이 줄고, 유지보수가 용이해짐
- 향상된 사용자 만족도: 평가 시간이 단축되고, UI/UX 개선으로 평가자들의 피드백이 좋아짐.
- ZERO VOC: 기존 레거시 서비스를 EOS(End Of Service)한 후에도 추가적인 기능 개선 문의는 들어오지만 VOC는 들어오지 않아서 10년 더 지난 서비스에서 계속 들어오던 VOC가 대폭 줄었다.
- 성능 모니터링: Sentry를 도입해 이슈 트래킹 및 앱 성능 지표 관리
- 팀 문화와 역량 향상
- Frontend/Backend 간 협업 프로세스 확립: API 스펙 협의 등
- 기술 세미나/스터디 진행: React 심화, 디자인 패턴 적용 등